﻿using System.Globalization;
using System.Runtime.InteropServices;

namespace Microsoft.Xna.Framework.Input
{
    /// <summary>
    /// Identifies whether the buttons on an Xbox 360 Controller are pressed or released.
    /// </summary>
	[StructLayout(LayoutKind.Sequential)]
    public struct GamePadButtons
	{
		#region Fields
		internal ButtonState _a;
		internal ButtonState _b;
		internal ButtonState _back;
		internal ButtonState _bigButton;
		internal ButtonState _leftShoulder;
		internal ButtonState _leftStick;
		internal ButtonState _rightShoulder;
		internal ButtonState _rightStick;
		internal ButtonState _start;
		internal ButtonState _x;
		internal ButtonState _y;
		#endregion

		#region Constructor
		/// <summary>
		/// Initializes a new instance of the GamePadButtons class, setting the specified buttons to pressed in.
        /// </summary>
		/// <param name="buttons">Buttons to initialize as pressed. Specify a single button or combine multiple buttons using a bitwise OR operation.</param>
        public GamePadButtons(Buttons buttons)
        {
			_a = ((buttons & Buttons.A) == Buttons.A) ? ButtonState.Pressed : ButtonState.Released;
			_b = ((buttons & Buttons.B) == Buttons.B) ? ButtonState.Pressed : ButtonState.Released;
			_x = ((buttons & Buttons.X) == Buttons.X) ? ButtonState.Pressed : ButtonState.Released;
			_y = ((buttons & Buttons.Y) == Buttons.Y) ? ButtonState.Pressed : ButtonState.Released;
			_back = ((buttons & Buttons.Back) == Buttons.Back) ? ButtonState.Pressed : ButtonState.Released;
			_start = ((buttons & Buttons.Start) == Buttons.Start) ? ButtonState.Pressed : ButtonState.Released;
			_leftStick = ((buttons & Buttons.LeftStick) == Buttons.LeftStick) ? ButtonState.Pressed : ButtonState.Released;
			_rightStick = ((buttons & Buttons.RightStick) == Buttons.RightStick) ? ButtonState.Pressed : ButtonState.Released;
			_leftShoulder = ((buttons & Buttons.LeftShoulder) == Buttons.LeftShoulder) ? ButtonState.Pressed : ButtonState.Released;
			_rightShoulder = ((buttons & Buttons.RightShoulder) == Buttons.RightShoulder) ? ButtonState.Pressed : ButtonState.Released;
			_bigButton = ((buttons & Buttons.BigButton) == Buttons.BigButton) ? ButtonState.Pressed : ButtonState.Released;
        }
        #endregion

        #region Properties
        /// <summary>
        /// Identifies whether the A button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState A
        {
			get { return _a; }
        }

        /// <summary>
        /// Identifies whether the B button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState B
        {
			get { return _b; }
        }

        /// <summary>
        /// Identifies whether the BACK button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState Back
        {
			get { return _back; }
        }

        /// <summary>
        /// Identifies whether the BigButton button is pressed.
        /// </summary>
        public ButtonState BigButton
        {
			get { return _bigButton; }
        }

        /// <summary>
        /// Identifies whether the left shoulder (bumper) button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState LeftShoulder
        {
			get { return _leftShoulder; }
        }

        /// <summary>
        /// Identifies whether the left stick button on the Xbox 360 Controller is pressed (the stick is "clicked" in).
        /// </summary>
        public ButtonState LeftStick
        {
			get { return _leftStick; }
        }

        /// <summary>
        /// Identifies whether the right shoulder (bumper) button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState RightShoulder
        {
			get { return _rightShoulder; }
        }

        /// <summary>
        /// Identifies whether the right stick button on the Xbox 360 Controller is pressed (the stick is "clicked" in).
        /// </summary>
        public ButtonState RightStick
        {
			get { return _rightStick; }
        }

        /// <summary>
        /// Identifies whether the START button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState Start
        {
			get { return _start; }
        }

        /// <summary>
        /// Identifies whether the X button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState X
        {
			get { return _x; }
        }

        /// <summary>
        /// Identifies whether the Y button on the Xbox 360 Controller is pressed.
        /// </summary>
        public ButtonState Y
        {
			get { return _y; }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// Returns a value that indicates whether the current instance is equal to a specified object.
        /// </summary>
        /// <param name="obj">Object with which to make the comparison.</param>
        public override bool Equals(object obj)
        {
			if (obj is GamePadButtons)
				return this == (GamePadButtons)obj;
			return false;
        }

        /// <summary>
        /// Gets the hash code for this instance.
        /// </summary>
        public override int GetHashCode()
        {
            return ((((((((((_a.GetHashCode() ^ _b.GetHashCode()) ^ _back.GetHashCode()) ^ _bigButton.GetHashCode()) ^ _leftShoulder.GetHashCode()) ^ _leftStick.GetHashCode()) ^ _rightShoulder.GetHashCode()) ^ _rightStick.GetHashCode()) ^ _start.GetHashCode()) ^ _x.GetHashCode()) ^ _y.GetHashCode());
        }

        /// <summary>
        /// Retrieves a string representation of this object.
        /// </summary>
        public override string ToString()
        {
			string str = string.Empty;
			if (this._a == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "A";
			}
			if (this._b == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "B";
			}
			if (this._x == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "X";
			}
			if (this._y == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "Y";
			}
			if (this._leftShoulder == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "LeftShoulder";
			}
			if (this._rightShoulder == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "RightShoulder";
			}
			if (this._leftStick == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "LeftStick";
			}
			if (this._rightStick == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "RightStick";
			}
			if (this._start == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "Start";
			}
			if (this._back == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "Back";
			}
			if (this._bigButton == ButtonState.Pressed)
			{
				str = str + ((str.Length != 0) ? " " : "") + "BigButton";
			}
			if (str.Length == 0)
			{
				str = "None";
			}
			return string.Format(CultureInfo.CurrentCulture, "{{Buttons:{0}}}", str);
        }
        #endregion

        #region Operators
		/// <summary>
		/// Determines whether two GamePadButtons instances are not equal.
		/// </summary>
		/// <param name="left">Object on the left of the equal sign.</param>
		/// <param name="right">Object on the right of the equal sign.</param>
		/// <returns>true if the instances are not equal; otherwise, false.</returns>
        public static bool operator !=(GamePadButtons left, GamePadButtons right)
        {
			return ((left._a != right._a) || (left._b != right._b) ||
					(left._back != right._back) || (left._bigButton != right._bigButton) ||
					(left._leftShoulder != right._leftShoulder) || (left._leftStick != right._leftStick) ||
					(left._rightShoulder != right._rightShoulder) || (left._rightStick != right._rightStick) ||
					(left._start != right._start) || (left._x != right._x) || (left._y != right._y));
        }

		/// <summary>
		/// Determines whether two GamePadButtons instances are equal.
		/// </summary>
		/// <param name="left">Object on the left of the equal sign.</param>
		/// <param name="right">Object on the right of the equal sign.</param>
		/// <returns>true if the instances are equal; otherwise, false.</returns>
        public static bool operator ==(GamePadButtons left, GamePadButtons right)
        {
            return ((left._a == right._a) && (left._b == right._b) &&
					(left._back == right._back) && (left._bigButton == right._bigButton) &&
					(left._leftShoulder == right._leftShoulder) && (left._leftStick == right._leftStick) &&
					(left._rightShoulder == right._rightShoulder) && (left._rightStick == right._rightStick) &&
					(left._start == right._start) && (left._x == right._x) && (left._y == right._y));
        }
        #endregion
    }
}
